<?php
// +----------------------------------------------------------------------
// | ZGUAN [ 致力于帮助更多的中小企业实现低成本数字化转型 ]
// +----------------------------------------------------------------------
// | Copyright (c) 2017~2024 https://www.zguan.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ZGUAN 并不是自由软件，未经许可不能去掉ZGUAN 相关版权
// +----------------------------------------------------------------------
// | Author: ZGUAN Team <admin@zguan.cn>  0769-82282996  15899929162
// +----------------------------------------------------------------------
namespace app\controller\api;

use api\oauth\exception\OauthException;
use app\common\repositories\users\UsersOauthRepository;
use app\common\services\CacheService;
use app\common\services\OauthService;
use app\controller\api\Base;
use app\http\response\api\StatusCode;
use app\validate\users\LoginValidate;
use app\common\repositories\users\UsersRepository;
use think\facade\Session;

class Login extends Base
{

    /**
     * 密码登录
     * @throws \Psr\SimpleCache\InvalidArgumentException
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function passwordLogin(UsersRepository $repository)
    {
        $param = $this->request->param([
            'account' => '',
            'password' => '',
            'verify_code' => ''
        ]);
        validate(LoginValidate::class)->scene('accountLogin')->check($param);
        $userInfo = $repository->getInfoByAccount($param['account']);
        if (!$userInfo) {
            return $this->error('账号或密码错误');
        }
        if (!$repository->passwordVerify($param['password'], $userInfo['password'])) {
            return $this->error('账号或密码错误');
        }
        if ($userInfo['status'] != 1) {
            return $this->error('此账号已被禁止登录');
        }
        $token = $repository->createToken($userInfo);
        $data = [
            'token' => $token,
            'userInfo' => $repository->showApiFilter($userInfo)
        ];
        return $this->success($data);
    }


    /**
     * 短信登录
     * @throws \Psr\SimpleCache\InvalidArgumentException
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function mobileSmsLogin(UsersRepository $repository)
    {
        validate(LoginValidate::class)->scene('mobileSmsLogin')->check($this->request->param());
        $mobile = $this->request->param('mobile');
        $smsCode = $this->request->param('sms_code');
        $userInfo = $repository->getInfoByMobile($mobile);
        # 短信验证
        sms_verify($this->request->propertyId ?? 0, $mobile, (string)$smsCode, config('sms.sms_type.LOGIN_VERIFY_CODE'));
        if ($userInfo) {
            if ($userInfo['status'] != 1) {

                return $this->error('此账号已被禁止登录');
            }
        } else {
            return $this->error('请先联系相关人员开通账号在登录');
        }
        $token = $repository->createToken($userInfo);

        $data = [
            'token' => $token,
            'userInfo' => $repository->showApiFilter($userInfo)
        ];
        return $this->success($data);
    }

    public function wechatMiniLogin(UsersRepository $usersRepository)
    {
        validate(LoginValidate::class)->scene('wechatLogin')->check($this->request->param());
        $wechatServer = OauthService::wechat($this->request->propertyId, OauthService::TYPE_WECHAT_MINI);

        $code = $this->request->param('code', '', 'trim');
        $iv = $this->request->param('iv', '', 'trim');
        $encryptedData = $this->request->param('encryptedData', '', 'trim');
        try {
            if ($code != '') {
                $weChatUserInfo = $wechatServer->getUserInfoMini($code, $iv, $encryptedData);
                $weChatUserInfo['openId'] = $weChatUserInfo['openid'];
                Session::set('wechat_session_key', $weChatUserInfo['session_key']);
            } else {
                $sessionKey = Session::get('wechat_session_key');

                if (empty($sessionKey)) {
                    return $this->error('登录失败', StatusCode::WECHAT_LOGIN_FAILED);
                }
                $weChatUserInfo = $wechatServer->decodeMini($iv, $sessionKey, $encryptedData);

                if (empty($weChatUserInfo) || $weChatUserInfo === false) {
                    return $this->error('登录失败', StatusCode::WECHAT_LOGIN_FAILED);
                }
            }
        } catch (OauthException $e) {
            return $this->error('登录失败', StatusCode::WECHAT_LOGIN_FAILED);
        }

        /** @var UsersOauthRepository $usersOauthRepository */
        $usersOauthRepository = app()->make(UsersOauthRepository::class);
        $oauthInfo = $usersOauthRepository->getByOpenId($weChatUserInfo['openId'], OauthService::TYPE_WECHAT_MINI, $this->request->propertyId);
        if ($oauthInfo) {
            $userInfo = $usersRepository->get($oauthInfo['user_id']);
            if ($userInfo['status'] != 1) {

                return $this->error('此账号已被禁止登录');
            }
        } else {
            $cacheKey = md5($weChatUserInfo['openId']);

            if (empty($weChatUserInfo['purePhoneNumber'])) {
                CacheService::create($this->request->propertyId)->set($cacheKey, $weChatUserInfo, 600);
                return $this->error('请绑定手机号', StatusCode::BIND_WECHAT_PHONE);
            }
            $requestWeChatUserInfo = CacheService::create($this->request->propertyId)->get($cacheKey);
            CacheService::create($this->request->propertyId)->delete($cacheKey);
            if (empty($weChatUserInfo['openId'])) {
                return $this->error('请求参数错误');
            }
            $mobile = $weChatUserInfo['purePhoneNumber'];
            $openId = $weChatUserInfo['openId'];
            $userInfo = $usersRepository->getInfoByMobile($mobile);
            if ($userInfo) {
                if ($userInfo['status'] != 1) {
                    return $this->error('此账号已被禁止登录');
                }
            } else {
                $userdData['mobile'] = $mobile;
                $userdData['account'] = $mobile;
                $userInfo = $usersRepository->register($userdData);
            }
            $usersOauthRepository->bindUser($this->request->propertyId, $userInfo['id'], $openId, OauthService::TYPE_WECHAT_MINI);
        }
        $token = $usersRepository->createToken($userInfo);
        $data = [
            'token' => $token,
            'userInfo' => $usersRepository->showApiFilter($userInfo)
        ];
        return $this->success($data);
    }

}